package com.cya.lotterysystem.service.impl;

import com.cya.lotterysystem.common.errcode.ServiceErrorCodeConstans;
import com.cya.lotterysystem.common.exception.ServiceException;
import com.cya.lotterysystem.common.utils.JacksonUtil;
import com.cya.lotterysystem.common.utils.RedisUtil;
import com.cya.lotterysystem.controller.param.DrawPrizeParam;
import com.cya.lotterysystem.controller.param.ShowWinningRecordsParam;
import com.cya.lotterysystem.dao.dataobject.*;
import com.cya.lotterysystem.dao.mapper.*;
import com.cya.lotterysystem.service.DrawPrizeService;
import com.cya.lotterysystem.service.dto.ActivityPrizeDO;
import com.cya.lotterysystem.service.dto.WinnerResultDTO;
import com.cya.lotterysystem.service.enums.ActivityPrizeStatusEnum;
import com.cya.lotterysystem.service.enums.ActivityPrizeTiersEnum;
import com.cya.lotterysystem.service.enums.ActivityStatusEnum;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.cya.lotterysystem.common.config.DirectRabbitConfig.EXCHANGE_NAME;
import static com.cya.lotterysystem.common.config.DirectRabbitConfig.ROUTING;

/**
 * @author ：陈奕安（3048279304@qq.com）
 * @date ：Created in 2025/11/6 22:29
 * @description：
 * @modified By：
 * @version:
 */
@Slf4j
@Service
public class DrawPrizeServiceImpl implements DrawPrizeService {

    private final  String WINNER_RECORDS_PREFIX="WINNER_RECORDS";

    private final  Long WINNER_RECORDS_TIMEOUT=60*60*24*2L;

    //mq
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private ActivityPrizeMapper activityPrizeMapper;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PrizeMapper prizeMapper;

    @Autowired
    private WinnerRecordMapper winnerRecordMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void drawPrize(DrawPrizeParam param) {

        //发消息:交换机，绑定的key，消息体
        Map<String,String> map=new HashMap<>();
        map.put("messageId",String.valueOf(UUID.randomUUID()));
        map.put("messageData", JacksonUtil.writeValueAsString(param));

            rabbitTemplate.convertAndSend(EXCHANGE_NAME,ROUTING,map);
        log.info("mq消息发送成功：map={}",JacksonUtil.writeValueAsString(map));


    }

    @Override
    public Boolean checkDrawPrizeParam(DrawPrizeParam param) {

        ActivityDO activityDO = activityMapper.selectById(param.getActivityId());
//        奖品是否存在可以从activity_prize查，因为保存activity做了本地事务，保证了一致性
    ActivityPrizeDO activityPrizeDO= activityPrizeMapper.selectByAPId(
                param.getActivityId(),param.getPrizeId()
        );
        //判断活动或奖品是否存在
            if (null==activityDO||null==activityDO){
//                log.info("校验抽奖请求失败！",ServiceErrorCodeConstans.ACTIVITY_OR_PRIZE_IS_EMPTY.getMsg());
        return false;
        }

//        判断活动是否有效
            if (activityDO.getStatus().equalsIgnoreCase(ActivityStatusEnum.COMPLETED.name())){
//            throw new ServiceException(ServiceErrorCodeConstans.ACTIVITY_COMPLETED);
                log.info("校验抽奖请求失败！",ServiceErrorCodeConstans.ACTIVITY_COMPLETED.getMsg());

            return false;
            }

//        判断奖品是否有效
if (activityPrizeDO.getStatus().equalsIgnoreCase(ActivityPrizeStatusEnum.COMPLETED.name())){
//    throw new ServiceException(ServiceErrorCodeConstans.ACTIVITY_PRIZE_COMPLETED);
    log.info("校验抽奖请求失败！",ServiceErrorCodeConstans.ACTIVITY_PRIZE_COMPLETED.getMsg());

    return false;
}

//        判断中奖者人数与奖品数一致
        if (activityPrizeDO.getPrizeAmount()!=param.getWinnerList().size()){
//            throw new ServiceException(ServiceErrorCodeConstans.WINNER_PRIZE_AMOUNT_ERROE);
            log.info("校验抽奖请求失败！",ServiceErrorCodeConstans.WINNER_PRIZE_AMOUNT_ERROE.getMsg());

            return false;

        }
        return true;


    }

    @Override
    public List<WinnerRecordDO> saveWinnerRecords(DrawPrizeParam param) {
        //查询相关信息，活动，人员，奖品 活动关联奖品
        ActivityDO activityDO = activityMapper.selectById(param.getActivityId());
     List<UserDo> userDoList=   userMapper.batchSelectByIds(param.getWinnerList().stream()
                .map(DrawPrizeParam.Winner::getUserId).
                collect(Collectors.toList()));
        log.info("userDoList 内容: {}", userDoList);  // 直接打印看结果

        PrizeDO prizeDO = prizeMapper.selectById(param.getPrizeId());

        ActivityPrizeDO activityPrizeDO = activityPrizeMapper.selectByAPId(param.getActivityId(), param.getPrizeId());



//        构造中奖者记录并保存
        List<WinnerRecordDO> winnerRecordDOList=userDoList.stream().map(
                userDo -> {
                    WinnerRecordDO winnerRecordDO=new WinnerRecordDO();
                    winnerRecordDO.setActivityId(activityDO.getId());
                    winnerRecordDO.setActivityName(activityDO.getActivityName());
                    winnerRecordDO.setPrizeId(prizeDO.getId());
                    winnerRecordDO.setPrizeName(prizeDO.getName());
                    winnerRecordDO.setPrizeTier(activityPrizeDO.getPrizeTiers());
                    winnerRecordDO.setWinnerEmail(userDo.getEmail());
                    winnerRecordDO.setWinnerId(userDo.getId());
                    winnerRecordDO.setWinnerName(userDo.getUserName());
                    winnerRecordDO.setWinnerPhoneNumber(userDo.getPhoneNumber());
                    winnerRecordDO.setWinningTime(param.getWinningTime());

                    return winnerRecordDO;


                }
        ).collect(Collectors.toList());

        winnerRecordMapper.batchInsert(winnerRecordDOList);


//        缓存中奖者记录
        //1.缓存奖品维度中奖记录（WinnerRecordactivityId-prizeId winnerRecordDOList
        cacheWinnerRecords(param.getActivityId()+ "_"+ param.getPrizeId(),//KEY
                winnerRecordDOList,
                WINNER_RECORDS_TIMEOUT);



        //2.缓存活动维度中奖记录WinnerRecord_activityId winnerRecordDOList
        if (activityDO.getStatus().equalsIgnoreCase(ActivityStatusEnum.COMPLETED.name())){
            //查询活动维度的全量中奖记录
           List<WinnerRecordDO> allList= winnerRecordMapper.selectByActivityId(param.getActivityId());

            cacheWinnerRecords(String.valueOf(param.getActivityId()) ,//KEY
                    allList,
                    WINNER_RECORDS_TIMEOUT);
        }
        return winnerRecordDOList;


    }

    @Override
    public void deleteRecord(Long activityId, Long prizeId) {

        if (null==activityId){
            log.warn("言删除中奖记录相关的活动id为空");
            return;
        }
        //删除对应数据表
        winnerRecordMapper.deleteRecords(activityId,prizeId);


        //删除缓存
        if (prizeId!=null){
            deleteWinningRecords(activityId+"_"+prizeId);
        }
        //无论是否传递prizeId，都需要删除活动维度的中奖记录
        deleteWinningRecords(String.valueOf(activityId));
    }

    @Override
    public List<WinnerResultDTO> getRecords(ShowWinningRecordsParam param) throws JsonProcessingException {
        //查询redis:奖品，活动
        String key=null==param.getPrizeId()?String.valueOf(param.getActivityId())
                :param.getActivityId()+"_"+param.getPrizeId();
    List<WinnerRecordDO> winnerRecordDOList=   getWinnerRecords(key);
    if (!CollectionUtils.isEmpty(winnerRecordDOList)){
        return converToWinningRecordDTOList(winnerRecordDOList);
    }

//        如果redis不存在，查库
         winnerRecordDOList= winnerRecordMapper.selectByActivityIdOrPrizeId(param.getActivityId(),param.getPrizeId());

        //记录存放到redis
        if (CollectionUtils.isEmpty(winnerRecordDOList)){

            log.info("查询的中奖记录为空！param：{}",
                    JacksonUtil.writeValueAsString(param));
            return Arrays.asList();
        }

        cacheWinnerRecords(key,winnerRecordDOList,WINNER_RECORDS_TIMEOUT);
        return converToWinningRecordDTOList(winnerRecordDOList);
    }


    private List<WinnerResultDTO> converToWinningRecordDTOList(List<WinnerRecordDO> winnerRecordDOList) {
        if (CollectionUtils.isEmpty(winnerRecordDOList)){
            return Arrays.asList();
        }
        return winnerRecordDOList.stream().map(
                winnerRecordDO -> {
                    WinnerResultDTO winnerResultDTO=new WinnerResultDTO();
                    winnerResultDTO.setWinnerId(winnerRecordDO.getWinnerId());
                    winnerResultDTO.setWinnerName(winnerRecordDO.getWinnerName());
                    winnerResultDTO.setPrizeName(winnerRecordDO.getPrizeName());
                    winnerResultDTO.setPrizeTier(
                            ActivityPrizeTiersEnum.forName(winnerRecordDO.getPrizeTier())
                    );
                    winnerResultDTO.setWinningTime(winnerRecordDO.getWinningTime());
                return  winnerResultDTO;
                }

        ).collect(Collectors.toList());

    }

    /**
     * 从缓存中删除中奖记录
     * @param key
     */
    private void deleteWinningRecords(String key) {
        try {
           if( redisUtil.hasKey(WINNER_RECORDS_PREFIX+key)){
               redisUtil.del(WINNER_RECORDS_PREFIX+key);
           }

        }catch (Exception e){
            log.error("删除中奖记录缓存异常：key：{}",key);
        }
    }

    /**
     * 缓存中奖记录
     * @param key
     * @param winnerRecordDOList
     * @param time
     */
    private void cacheWinnerRecords(String key,
                                    List<WinnerRecordDO> winnerRecordDOList,
                                    Long time) {
        String str="";
        try {
            if (!StringUtils.hasText(key)|| CollectionUtils.isEmpty(winnerRecordDOList)){
                log.warn("要缓存的内容为空！key:{},value:{}",
                        key,JacksonUtil.writeValueAsString(winnerRecordDOList));
                return;
            }
            str=JacksonUtil.writeValueAsString(winnerRecordDOList);
            redisUtil.set(WINNER_RECORDS_PREFIX+key,
                    str,
                    time);
        }catch (Exception e){
            log.error("缓存中奖记录异常：key：{}，value：{}",WINNER_RECORDS_PREFIX+key,str);
        }
        }

    /**
     * 从缓存中获取中奖记录
     * @param key
     * @return
     * @throws JsonProcessingException
     */
        private List<WinnerRecordDO> getWinnerRecords(String key) throws JsonProcessingException {

        try {
            if (key==null){
                log.warn("要从缓存中查询的中奖记录key为空！");
                return Arrays.asList();

            }
            String str = redisUtil.get(WINNER_RECORDS_PREFIX + key);
            if (!StringUtils.hasText(str)){
                return Arrays.asList();
            }
            List<WinnerRecordDO> winnerRecordDOList=
                    JacksonUtil.readListValue(str,WinnerRecordDO.class);
            return winnerRecordDOList;
        }catch (Exception e){
            log.error("从缓存查询中奖记录异常：key：{}",WINNER_RECORDS_PREFIX+key);
            return Arrays.asList();

        }

        }


}